package com.hulk.dryad.manage.framework.idempotent.expression;


import com.hulk.dryad.common.annotation.Idempotent;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author hulk
 * <p>
 * 默认key 抽取， 优先根据 spel 处理
 * @date 2020-09-25
 */
public class IdempotentKeyExpressionResolver implements IdempotentKeyResolver {

//	private static final SpelExpressionParser PARSER = new SpelExpressionParser();
//
//	private static final LocalVariableTableParameterNameDiscoverer DISCOVERER = new LocalVariableTableParameterNameDiscoverer();
//
//	@Override
//	public String getKeyName(JoinPoint point, Idempotent idempotent) {
//		Object[] arguments = point.getArgs();
//		String[] params = DISCOVERER.getParameterNames(getMethod(point));
//		StandardEvaluationContext context = new StandardEvaluationContext();
//
//		for (int len = 0; len < params.length; len++) {
//			context.setVariable(params[len], arguments[len]);
//		}
//
//		Expression expression = PARSER.parseExpression(idempotent.keys());
//		return expression.getValue(context, String.class);
//	}

	private static final ParameterNameDiscoverer NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
	private static final ExpressionParser PARSER = new SpelExpressionParser();

	@Override
	public String getKeyName(JoinPoint joinPoint, Idempotent idempotent) {
		List<String> keyList = new ArrayList<>();
		Method method = getMethod(joinPoint);
		if (!ObjectUtils.isEmpty(idempotent.keys())) {{
			List<String> definitionKeys = getSpelDefinitionKey(idempotent.keys(), method, joinPoint.getArgs());
			keyList.addAll(definitionKeys);
		}}
		return StringUtils.collectionToDelimitedString(keyList,"-","","");
	}
	/**
	 * 根据切点解析方法信息
	 * @param joinPoint 切点信息
	 * @return Method 原信息
	 */
	private Method getMethod(JoinPoint joinPoint) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		if (method.getDeclaringClass().isInterface()) {
			try {
				method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(),
						method.getParameterTypes());
			}
			catch (SecurityException | NoSuchMethodException e) {
				throw new RuntimeException(e);
			}
		}
		return method;
	}

	private List<String> getSpelDefinitionKey(String[] definitionKeys, Method method, Object[] parameterValues) {
		EvaluationContext context = new MethodBasedEvaluationContext(null, method, parameterValues, NAME_DISCOVERER);
		List<String> definitionKeyList = new ArrayList<>(definitionKeys.length);
		for (String definitionKey : definitionKeys) {
			if (!StringUtils.isEmpty(definitionKey)) {
				Object objKey = PARSER.parseExpression(definitionKey).getValue(context);
				definitionKeyList.add(ObjectUtils.nullSafeToString(objKey));
			}
		}
		return definitionKeyList;
	}

}